#include "sylar.h"
#include <stdint.h>
namespace sylar
{
    static thread_local Thread *t_thread = nullptr;
    static thread_local std::string t_thread_name = "NONAME";
    static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
    Semaphore::Semaphore(uint32_t count)
    {
        if (sem_init(&m_semaphore, 0, count))
        {
            throw std::logic_error("Semaphore::Semaphore() sem_init() error\n");
        }
    }
    Semaphore::~Semaphore()
    {
        sem_destroy(&m_semaphore);
    }
    void Semaphore::wait()
    {
        if (sem_wait(&m_semaphore))
        {
            throw std::logic_error("Semaphore::wait() error\n");
        }
    }
    void Semaphore::notify()
    {
        if (sem_post(&m_semaphore))
        {
            throw std::logic_error("Semaphore::notify() error\n");
            ;
        }
    }
    Thread *Thread::GetThis()
    {
        return t_thread;
    }
    const std::string &Thread::getName()
    {
        return t_thread_name;
    }
    const std::string &Thread::GetName()
    {
        return t_thread_name;
    }
    void Thread::SetName(const std::string &name)
    {
        if (t_thread)
        {
            t_thread->m_name = name;
        }
        t_thread_name = name;
    }

    Thread::Thread(std::function<void()> cb, const std::string &name)
    {
        if (name.empty())
        {
            m_name = "NONAME";
        }
        m_name = name;
        m_cb = cb;
        int rt = pthread_create(&m_thread, nullptr, &Thread::run, this);
        if (rt)
        {
            SYLAR_LOG_ERROR(g_logger) << "pthread_create thread fail , rt =" << rt << "name = " << name;
            throw std::logic_error("pthread_create error");
        }
        m_semaphore.wait();
    }
    Thread::~Thread()
    {
        if (m_thread)
        {
            pthread_detach(m_thread);
        }
    }
    void Thread::join()
    {
        if (m_thread)
        {
            int rt = pthread_join(m_thread, nullptr);
            if (rt)
            {
                SYLAR_LOG_ERROR(g_logger) << "pthread_join threadf fail, rt =" << rt << "name :" << m_name;
                throw std::logic_error("pthread_join error");
            }
        }
        m_thread = 0;
    }
    void *Thread::run(void *arg)
    {
        Thread *thread = static_cast<Thread *>(arg);
        t_thread = thread;
        thread->m_id = sylar::GetThreadId();
        t_thread_name = thread->m_name;
        pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str());
        std::function<void()> cb;
        cb.swap(thread->m_cb);
        thread->m_semaphore.notify();
        cb();
        return nullptr;
    }
}